package com.uduemc.biso.node.web.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.github.pagehelper.PageInfo;
import com.uduemc.biso.core.extities.node.custom.LoginNode;
import com.uduemc.biso.core.utils.JsonResult;
import com.uduemc.biso.core.utils.RestResult;
import com.uduemc.biso.core.utils.ResultUtil;
import com.uduemc.biso.node.core.common.feign.CArticleFeign;
import com.uduemc.biso.node.core.dto.FeignFindInfosBySystemIdAndIds;
import com.uduemc.biso.node.core.dto.FeignSystemTotal;
import com.uduemc.biso.node.core.entities.SArticle;
import com.uduemc.biso.node.core.entities.SArticleSlug;
import com.uduemc.biso.node.core.entities.SSeoItem;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.core.entities.custom.Article;
import com.uduemc.biso.node.core.entities.custom.CategoryQuote;
import com.uduemc.biso.node.core.entities.custom.RepertoryQuote;
import com.uduemc.biso.node.core.feign.SArticleFeign;
import com.uduemc.biso.node.core.feign.SArticleSlugFeign;
import com.uduemc.biso.node.core.node.dto.FeignArticleTableData;
import com.uduemc.biso.node.core.node.extities.ArticleTableData;
import com.uduemc.biso.node.core.node.feign.NArticleFeign;
import com.uduemc.biso.node.core.utils.RestResultUtil;
import com.uduemc.biso.node.web.api.component.RequestHolder;
import com.uduemc.biso.node.web.api.dto.RequestArticleTableDataList;
import com.uduemc.biso.node.web.api.dto.RequestArtilce;
import com.uduemc.biso.node.web.api.dto.item.ItemCustomLink;
import com.uduemc.biso.node.web.api.service.ArticleService;
import com.uduemc.biso.node.web.api.service.LoginService;
import com.uduemc.biso.node.web.api.service.SystemItemCustomLinkService;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Resource
    private SArticleFeign sArticleFeign;

    @Resource
    private RequestHolder requestHolder;

    @Resource
    private CArticleFeign cArticleFeign;

    @Resource
    private NArticleFeign nArticleFeign;

    @Resource
    private SArticleSlugFeign sArticleSlugFeign;

    @Resource
    private SystemItemCustomLinkService systemItemCustomLinkServiceImpl;

    @Resource
    private LoginService loginServiceImpl;

    @Override
    public boolean existByHostSiteIdAndId(long hostId, long siteId, long id)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleFeign.existByHostSiteIdAndId(hostId, siteId, id);
        Boolean data = RestResultUtil.data(restResult, Boolean.class);
        return data;
    }

    @Override
    public boolean existCurrentByHostSiteIdAndId(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        return existByHostSiteIdAndId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), id);
    }

    @Override
    public Article save(RequestArtilce requestArtilce) throws IOException {
        // 首先通过 requestSArtilce 获取 Article数据
        Article article = new Article();

        // 设置 sArticle
        SArticle sArticle = requestArtilce.getSArticle(requestHolder);
        article.setSArticle(sArticle);

        // 设置 RepertoryQuote
        RepertoryQuote repertoryQuote = requestArtilce.getRepertoryQuote(requestHolder);
        article.setRepertoryQuote(repertoryQuote);

        // 文章文件
        List<RepertoryQuote> makeFileList = requestArtilce.makeFileList(requestHolder);
        article.setFileList(makeFileList);

        // 设置 CategoryQuote 分类
        CategoryQuote categoryQuote = requestArtilce.getCategoryQuote(requestHolder);
        article.setCategoryQuote(categoryQuote);

        // 设置 slug 短标题以及排版信息
        SArticleSlug sArticleSlug = requestArtilce.getSArticleSlug(requestHolder);
        article.setSArticleSlug(sArticleSlug);

        // 设置 SSeoItem
        SSeoItem sSeoItem = requestArtilce.getSSeoItem(requestHolder);
        article.setSSeoItem(sSeoItem);

        Article data = null;
        if (article.getSArticle().getId() == null) {
            // 请求微服务添加
            RestResult restResult = cArticleFeign.insert(article);
            data = RestResultUtil.data(restResult, Article.class);

            if (data != null && data.getSArticle() != null) {
                // 记录新增情况下的产品使用的分类
                List<Long> categoryIds = new ArrayList<>();
                if (data.getCategoryQuote() == null) {
                    categoryIds = null;
                } else {
                    categoryIds.add(data.getCategoryQuote().getSCategories().getId());
                }
                LoginNode loginNode = requestHolder.getCurrentLoginNode();
                loginNode.saveSystemCategory(data.getSArticle().getSystemId(), categoryIds);
                loginServiceImpl.recacheLoginNode(loginNode);
            }

        } else {
            // 请求微服务修改
            RestResult restResult = cArticleFeign.update(article);
            data = RestResultUtil.data(restResult, Article.class);
        }

        if (data != null) {
            ItemCustomLink customLink = requestArtilce.getItemCustomLink();
            if (customLink != null) {
                makeCustomLink(data, customLink);
            } else {
                // 删除动作
                systemItemCustomLinkServiceImpl.deleteByHostSiteSystemItemId(data.getSArticle().getHostId(), data.getSArticle().getSiteId(),
                        data.getSArticle().getSystemId(), data.getSArticle().getId());
            }
        }

        return data;
    }

    @Override
    public Article infoCurrent(long articleId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.findByHostSiteArticleId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), articleId);
        Article data = RestResultUtil.data(restResult, Article.class);
        makeCustomLink(data);
        return data;
    }

    @Override
    public PageInfo<ArticleTableData> getInfosByRequestArticleTableDataList(RequestArticleTableDataList requestArticleTableDataList)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {

        FeignArticleTableData feignArticleTableData = requestArticleTableDataList.getFeignArticleTableData(requestHolder);
        feignArticleTableData.setIsRefuse((short) 0);

        RestResult restResult = nArticleFeign.tableDataList(feignArticleTableData);
        @SuppressWarnings("unchecked")
        PageInfo<ArticleTableData> data = (PageInfo<ArticleTableData>) RestResultUtil.data(restResult, new TypeReference<PageInfo<ArticleTableData>>() {
        });
        return data;
    }

    @Override
    public SArticle getCurrentInfoById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleFeign.findByHostSiteIdAndId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), id);
        SArticle data = RestResultUtil.data(restResult, SArticle.class);
        return data;
    }

    @Override
    public boolean updateBySArticle(SArticle sArticle) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleFeign.updateById(sArticle);
        SArticle data = RestResultUtil.data(restResult, SArticle.class);
        return data != null;
    }

    @Override
    public boolean deletes(List<SArticle> listSArticle) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.deleteByHostSiteIdAndArticleIds(listSArticle);
        Boolean bool = RestResultUtil.data(restResult, Boolean.class);
        return bool;
    }

    @Override
    public boolean existCurrentSlugById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleSlugFeign.findOne(id);
        SArticleSlug data = RestResultUtil.data(restResult, SArticleSlug.class);
        return data != null;
    }

    @Override
    public SArticleSlug findCurrentSlugById(long id) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleSlugFeign.findOne(id);
        SArticleSlug data = RestResultUtil.data(restResult, SArticleSlug.class);
        return data;
    }

    @Override
    public Map<Long, List<SArticleSlug>> getSlugInfoBySystem(SSystem sSystem)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleSlugFeign.findByHostSiteSystemIdAndOrderBySArticle(requestHolder.getHost().getId(),
                requestHolder.getCurrentSite().getId(), sSystem.getId());

        @SuppressWarnings("unchecked")
        List<SArticleSlug> data = (List<SArticleSlug>) RestResultUtil.data(restResult, new TypeReference<List<SArticleSlug>>() {
        });
        if (CollectionUtils.isEmpty(data)) {
            return null;
        }

        Map<Long, List<SArticleSlug>> result = new HashMap<>();

        for (SArticleSlug sArticleSlug : data) {
            Long parentId = sArticleSlug.getParentId();
            if (result.containsKey(parentId)) {
                List<SArticleSlug> list = result.get(parentId);
                list.add(sArticleSlug);
            } else {
                List<SArticleSlug> list = new ArrayList<>();
                list.add(sArticleSlug);
                result.put(parentId, list);
            }
        }

        return result;
    }

    @Override
    public PageInfo<Article> infosByHostSiteSystemCategoryIdAndPageLimit(long hostId, long siteId, long systemId, long categoryId, String name, int page,
                                                                         int limit) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.findInfosBySystemCategoryIdAndPageLimit(hostId, siteId, systemId, categoryId, name, page, limit);
        @SuppressWarnings("unchecked")
        PageInfo<Article> data = (PageInfo<Article>) RestResultUtil.data(restResult, new TypeReference<PageInfo<Article>>() {
        });
        return data;
    }

    @Override
    public PageInfo<Article> infosCurrentBySystemCategoryIdAndPageLimit(long systemId, long categoryId, String name, int page, int limit)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getHost().getId();
        Long siteId = requestHolder.getCurrentSite().getId();
        return infosByHostSiteSystemCategoryIdAndPageLimit(hostId, siteId, systemId, categoryId, name, page, limit);
    }

    @Override
    public int totalCurrentBySystemCategoryId(long systemId, long categoryId)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.totalByHostSiteSystemCategoryId(requestHolder.getHost().getId(), requestHolder.getCurrentSite().getId(), systemId,
                categoryId);
        Integer data = RestResultUtil.data(restResult, Integer.class);
        return data.intValue();
    }

    @Override
    public List<Article> infosCurrentBySystemIdAndIds(FeignFindInfosBySystemIdAndIds feignFindInfosBySystemIdAndIds)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        feignFindInfosBySystemIdAndIds.setHostId(requestHolder.getHost().getId()).setSiteId(requestHolder.getCurrentSite().getId());
        RestResult restResult = cArticleFeign.findInfosBySystemIdAndIds(feignFindInfosBySystemIdAndIds);
        @SuppressWarnings("unchecked")
        List<Article> data = (List<Article>) RestResultUtil.data(restResult, new TypeReference<List<Article>>() {
        });
        if (CollectionUtils.isEmpty(data)) {
            return null;
        }
        return data;
    }

    @Override
    public int totalByHostId() throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getCurrentSite().getId();
        return totalByHostId(hostId);
    }

    @Override
    public int totalByHostId(long hostId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = sArticleFeign.totalByHostId(hostId);
        Integer data = ResultUtil.data(restResult, Integer.class);
        if (data == null) {
            return 0;
        }
        return data.intValue();
    }

    @Override
    public int totalByHostSystemId(long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        Long hostId = requestHolder.getCurrentSite().getId();
        return totalByHostSystemId(hostId, systemId);
    }

    @Override
    public int totalByHostSystemId(long hostId, long systemId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignSystemTotal feignSystemTotal = new FeignSystemTotal();
        feignSystemTotal.setHostId(hostId).setSystemId(systemId);
        RestResult restResult = sArticleFeign.totalByFeignSystemTotal(feignSystemTotal);
        Integer data = ResultUtil.data(restResult, Integer.class);
        if (data == null) {
            return 0;
        }
        return data.intValue();
    }

//	@Override
//	public List<SArticle> findInfosByHostSiteSystemAndIds(FeignSystemDataInfos feignSystemDataInfos)
//			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
//		RestResult restResult = sArticleFeign.findInfosByHostSiteSystemAndIds(feignSystemDataInfos);
//		@SuppressWarnings("unchecked")
//		List<SArticle> listSArticle = (ArrayList<SArticle>) RestResultUtil.data(restResult, new TypeReference<ArrayList<SArticle>>() {
//		});
//		return listSArticle;
//	}

    @Override
    public PageInfo<ArticleTableData> getRecycleInfosByRequestArticleTableDataList(RequestArticleTableDataList requestArticleTableDataList)
            throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        FeignArticleTableData feignArticleTableData = requestArticleTableDataList.getFeignArticleTableData(requestHolder);
        feignArticleTableData.setIsRefuse((short) 1);

        RestResult restResult = nArticleFeign.tableDataList(feignArticleTableData);
        @SuppressWarnings("unchecked")
        PageInfo<ArticleTableData> data = (PageInfo<ArticleTableData>) RestResultUtil.data(restResult, new TypeReference<PageInfo<ArticleTableData>>() {
        });
        return data;
    }

    @Override
    public boolean reductionRecycle(List<SArticle> listSArticle) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.reductionByListSArticle(listSArticle);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public boolean cleanRecycle(List<SArticle> listSArticle) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.cleanRecycle(listSArticle);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    @Override
    public boolean cleanRecycleAll(SSystem sSystem) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
        RestResult restResult = cArticleFeign.cleanRecycleAll(sSystem);
        return RestResultUtil.data(restResult, Boolean.class);
    }

    protected void makeCustomLink(Article data, ItemCustomLink customLink) throws IOException {
        if (data != null) {
            if (customLink != null) {
                if (data.getSArticle() != null) {
                    SArticle datasSArticle = data.getSArticle();
                    if (datasSArticle.getId() != null) {
                        Long sArticleId = datasSArticle.getId();
                        short status = customLink.getStatus();
                        List<String> path = customLink.getPath();
                        List<String> collect = path.stream().filter(StrUtil::isNotBlank).collect(Collectors.toList());
                        JsonResult saveItemCustomLink = systemItemCustomLinkServiceImpl.saveItemCustomLink(datasSArticle.getSystemId(), sArticleId, status,
                                CollUtil.join(collect, "/"), "");
                        if (saveItemCustomLink.getCode() == 200) {
                            makeCustomLink(data);
                        }
                    }
                }
            }
        }
    }

    protected void makeCustomLink(Article data) throws IOException {
        if (data != null) {
            if (data.getSArticle() != null) {
                SArticle datasSArticle = data.getSArticle();
                if (datasSArticle.getId() != null) {
                    JsonResult itemCustomLink = systemItemCustomLinkServiceImpl.itemCustomLink(datasSArticle.getSystemId(), datasSArticle.getId());
                    if (itemCustomLink.getCode() == 200) {
                        Object dataObject = itemCustomLink.getData();
                        data.setCustomLink(dataObject);
                    }
                }
            }
        }
    }

}
